from django.db import models
from django.db.models import Sum, Avg
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.postgres.fields import ArrayField
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User
from django.urls import reverse
from datetime import timedelta
from .apps import GeneralConfig
import hashlib
import math

app_name = GeneralConfig.name


def calculate_price(price_in):
    price_in = float(price_in)
    if price_in > 1000:
        return math.ceil(price_in / 100) * 100
    else:
        return math.ceil(price_in / 10) * 10


class BankAccount(models.Model):
    bank = models.CharField(_('银行-中文名'), max_length=200, null=True, blank=True)
    bank_en = models.CharField(_('银行-英文名'), max_length=200, null=True, blank=True)
    beneficiary_name = models.CharField(_('收款人'), max_length=200, null=True, blank=True)
    beneficiary_name_en = models.CharField(_('收款人-英文'), max_length=200, null=True, blank=True)
    beneficiary_address = models.CharField(_('收款人地址'), max_length=200, null=True, blank=True)
    beneficiary_address_en = models.CharField(_('收款人地址-英文'), max_length=200, null=True, blank=True)
    swift_code = models.CharField(_('Swift'), max_length=50, null=True, blank=True)
    bank_account = models.CharField(_('银行卡号'), max_length=50, null=True, blank=True)
    bank_address = models.CharField(_('银行地址-中文'), max_length=200, null=True, blank=True)
    bank_address_en = models.CharField(_('银行地址-英文'), max_length=200, null=True, blank=True)
    desc = models.TextField(_('备注'), max_length=1000, null=True, blank=True)
    is_active = models.BooleanField(_('可用'), default=True)

    objects = models.Manager()

    class Meta:
        verbose_name = _('收款帐号')
        verbose_name_plural = _('收款帐号')

    def __str__(self):
        return '{0} {1}'.format(self.bank, self.bank_account)


class SubCompany(models.Model):
    company_name_en = models.CharField(_('公司英文名'), max_length=200, null=True)
    company_name_cn = models.CharField(_('公司中文名'), max_length=200, null=True)
    company_address_en = models.CharField(_('公司英文地址'), max_length=200, null=True, blank=True)
    company_address_cn = models.CharField(_('公司中文地址'), max_length=200, null=True)
    company_contact_en = models.CharField(_('公司英文联系方式'), max_length=200, null=True)
    company_contact_cn = models.CharField(_('公司中文联系方式'), max_length=200, null=True)
    company_web_en = models.CharField(_('公司英文网站'), max_length=200, null=True, blank=True)
    company_web_cn = models.CharField(_('公司中文网站'), max_length=200, null=True, blank=True)
    tax_code = models.CharField(_('税号'), max_length=100, null=True, blank=True)
    fax = models.CharField(_('传真'), max_length=100, null=True, blank=True)
    logo = models.ImageField(_('Logo'), upload_to='company', null=True, blank=True)

    objects = models.Manager()

    class Meta:
        verbose_name = _('对接公司')
        verbose_name_plural = _('对接公司')

    def __str__(self):
        return '{0}'.format(self. company_name_cn)


class TypeCategory(models.Model):
    type_category_en = models.CharField(_('类型归类英文'), max_length=100)
    type_category_cn = models.CharField(_('类型归类中文'), max_length=100)
    type_category_desc_en = models.CharField(_('类型归类介绍英文'), max_length=200, null=True, blank=True)
    type_category_desc_cn = models.CharField(_('类型归类介绍中文'), max_length=200, null=True, blank=True)

    objects = models.Manager()

    class Meta:
        verbose_name = _('类型归类')
        verbose_name_plural = _('类型归类')

    def __str__(self):
        return '{0}'.format(self.type_category_cn)


class EquipmentType(models.Model):
    equipment_type_en = models.CharField(_('设备类型英文'), max_length=100)
    equipment_type_cn = models.CharField(_('设备类型中文'), max_length=100)
    equipment_type_desc_en = models.CharField(_('设备类型介绍英文'), max_length=200, null=True, blank=True)
    equipment_type_desc_cn = models.CharField(_('设备类型介绍中文'), max_length=200, null=True, blank=True)
    equipment_type_color = models.CharField(_('颜色'), max_length=10, null=True, blank=True)
    equipment_type_image = models.TextField(_('图片'), max_length=4000, null=True, blank=True)
    type_category = models.ManyToManyField(
        TypeCategory,
        blank=True,
        verbose_name=_('类型归类')
    )
    equipment_type_code = models.CharField(_('设备类型编号'), max_length=100, null=True, default='00')
    is_part = models.BooleanField(_('备件'), default=False)

    objects = models.Manager()

    class Meta:
        verbose_name = _('设备类型')
        verbose_name_plural = _('设备类型')

    def __str__(self):
        return '{0}'.format(self.equipment_type_cn)


class EquipmentSize(models.Model):
    equipment_size_en = models.CharField(_('设备规格英文'), max_length=100, unique=True)
    equipment_size_cn = models.CharField(_('设备规格中文'), max_length=100, unique=True)

    objects = models.Manager()

    class Meta:
        verbose_name = _('设备规格')
        verbose_name_plural = _('设备规格')

    def __str__(self):
        return '{0}'.format(self.equipment_size_en)


class EquipmentUnit(models.Model):
    equipment_unit_en = models.CharField(_('设备单位英文'), max_length=100)
    equipment_unit_cn = models.CharField(_('设备单位中文'), max_length=100)

    objects = models.Manager()

    class Meta:
        verbose_name = _('设备单位')
        verbose_name_plural = _('设备单位')

    def __str__(self):
        return '{0} {1}'.format(self.equipment_unit_cn, self.equipment_unit_en)


class PowerType(models.Model):
    power_type_en = models.CharField(_('电源类型英文'), max_length=100)
    power_type_cn = models.CharField(_('电源类型中文'), max_length=100)

    objects = models.Manager()

    class Meta:
        verbose_name = _('电源类型')
        verbose_name_plural = _('电源类型')

    def __str__(self):
        return '{0} {1}'.format(self.power_type_en, self.power_type_cn)


class Equipment(models.Model):
    equipment_code = models.CharField(_('设备编号'), max_length=100, null=True, blank=True, unique=True)
    equipment_code_auto = models.CharField(_('设备编码'), max_length=100, null=True, blank=True)
    equipment_exp_code = models.CharField(_('设备海关编码'), max_length=100, null=True, blank=True)
    equipment_en = models.CharField(_('设备英文名'), max_length=100)
    equipment_cn = models.CharField(_('设备中文名'), max_length=100)
    cost = models.DecimalField(_('设备成本'), max_digits=12, decimal_places=2, null=True, blank=True)
    basic_price = models.DecimalField(_('市场报价'), max_digits=12, decimal_places=2, null=True, blank=True)
    dist_price = models.DecimalField(_('工厂底价'), max_digits=12, decimal_places=2, null=True, blank=True)
    equipment_type = models.ForeignKey(
        EquipmentType,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name=_('设备类型'),
    )
    equipment_size = models.ManyToManyField(
        EquipmentSize,
        blank=True,
        verbose_name=_('设备规格')
    )
    equipment_para_en = models.TextField(_('设备参数英文'), max_length=10000, null=True, blank=True)
    equipment_para_cn = models.TextField(_('设备参数中文'), max_length=10000, null=True, blank=True)
    equipment_unit = models.ForeignKey(
        EquipmentUnit,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name=_('设备单位'),
    )
    length = models.BigIntegerField(_('长/mm'), null=True, blank=True)
    width = models.BigIntegerField(_('宽/mm'), null=True, blank=True)
    height = models.BigIntegerField(_('高/mm'), null=True, blank=True)
    weight = models.BigIntegerField(_('重量/kg'), null=True, blank=True)
    power = models.DecimalField(_('功率/kw'), max_digits=7, decimal_places=3, null=True, blank=True)
    power_type = models.ForeignKey(
        PowerType,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('电源类型')
    )
    related_equipment = models.ManyToManyField('self', verbose_name=_('关联设备'), blank=True)
    related_materials = models.TextField(_('关联原料'), max_length=10000, null=True, blank=True)
    drawing_en = models.FileField(_('英文图纸'), upload_to='{0}/sb/tz_en'.format(app_name),
                                  null=True, blank=True)
    file_en = models.FileField(_('英文资料'), upload_to='{0}/sb/wj_en'.format(app_name),
                               null=True, blank=True)
    drawing_cn = models.FileField(_('中文图纸'), upload_to='{0}/sb/tz_en'.format(app_name),
                                  null=True, blank=True)
    file_cn = models.FileField(_('中文资料'), upload_to='{0}/sb/wj_cn'.format(app_name),
                               null=True, blank=True)
    file_3d = models.FileField(_('3D图形文件'), upload_to='{0}/sb/3d'.format(app_name),
                               null=True, blank=True)
    equipment_img = models.FileField(_('设备图片'), upload_to='{0}/sb/img'.format(app_name),
                                     null=True, blank=True)
    file_3s = models.FileField(_('设备3视图'), upload_to='{0}/sb/3d'.format(app_name),
                               null=True, blank=True)
    is_active = models.BooleanField(_('可销售'), default=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='equipment_created_by'
    )
    datetime_created = models.DateTimeField(auto_now_add=True)
    datetime_updated = models.DateTimeField(auto_now=True)

    objects = models.Manager()

    def get_absolute_url(self):
        return reverse('{0}:equipment_detail'.format(app_name), kwargs={'pk': str(self.pk)})

    @property
    def create_equipment_code_auto(self):
        if self.equipment_type and self.pk:
            code_first = getattr(self.equipment_type, 'equipment_type_code', None)
            return '{0}{1}'.format(code_first, str(self.pk).zfill(6))
        return None

    def save(self, *args, **kwargs):
        if self.create_equipment_code_auto and not self.equipment_code_auto:
            self.equipment_code_auto = self.create_equipment_code_auto
        super(Equipment, self).save(*args, **kwargs)

    @property
    def size_para(self):
        if self.length and self.width and self.height:
            return '{3}: {0}*{1}*{2} mm'.format(self.height, self.width, self.length, _('长宽高'))
        return None

    @property
    def related_orders(self):
        related_order_items = ItemList.objects.filter(equipment__pk=self.pk).order_by('-datetime_created')
        if related_order_items:
            return related_order_items
        return None

    @property
    def order_count(self):
        related_order_items = ItemList.objects.filter(equipment__pk=self.pk).order_by('-datetime_created')
        if related_order_items:
            return related_order_items.count()
        return ''

    @property
    def related_assemblies(self):
        assemblies = EquipmentAssembly.objects.filter(equipment__pk=self.pk).order_by('-datetime_created')
        if assemblies:
            return assemblies
        return None

    @property
    def assembly_count(self):
        assemblies = EquipmentAssembly.objects.filter(equipment__pk=self.pk).order_by('-datetime_created')
        if assemblies:
            return assemblies.count()
        return ''

    @property
    def amount_left(self):
        warehouse_list = Warehouse.objects.all()
        e_i_l = EquipmentIn.objects.filter(equipment_id=self.pk)
        e_o_l = EquipmentOut.objects.filter(equipment_id=self.pk)
        if e_i_l:
            e_left = dict()
            e_left['total'] = 0
            if warehouse_list:
                for w in warehouse_list:
                    e_t_i_amount = 0
                    e_t_o_amount = 0
                    e_i = e_i_l.filter(warehouse_id=w.pk).aggregate(t_i=Sum('amount'))
                    e_o = e_o_l.filter(warehouse_id=w.pk).aggregate(t_o=Sum('amount'))
                    if e_i.get('t_i'):
                        e_t_i_amount = e_i.get('t_i')
                    if e_o.get('t_o'):
                        e_t_o_amount = e_o.get('t_o')
                    e_left['{0}'.format(w.name)] = e_t_i_amount - e_t_o_amount
                    e_left['total'] += (e_t_i_amount - e_t_o_amount)
            return e_left
        return {'total': 0}

    @property
    def amount_left_total(self):
        if self.amount_left:
            return self.amount_left.get('total')
        return 0

    class Meta:
        ordering = ['equipment_code']
        verbose_name = _('设备')
        verbose_name_plural = _('设备')
        permissions = (
            ("view_equipment_basic_price", _("可以查看设备的基础价格")),
            ("view_equipment_dist_price", _("可以查看设备的经销商价格")),
            ("change_equipment_price", _("可以更改设备的价格")),
        )

    def __str__(self):
        if self.amount_left:
            return '[{0}] ({1}) {2} / {3} ({4}) {5}'.format(
                self.pk, self.equipment_code, self.equipment_cn, self.equipment_en,
                self.equipment_type, self.amount_left)
        else:
            return '[{0}] ({1}) {2} / {3} ({4})'.format(
                self.pk, self.equipment_code, self.equipment_cn, self.equipment_en, self.equipment_type)


class RelationLevel(models.Model):
    relation_level_code = models.CharField(_('编号'), max_length=100)
    relation_level_cn = models.CharField(_('关系中文'), max_length=100)
    relation_level_en = models.CharField(_('关系英文'), max_length=100)

    objects = models.Manager()

    class Meta:
        ordering = ['id']
        verbose_name = _('关系等级')
        verbose_name_plural = _('关系等级')

    def __str__(self):
        return '{0} {1} {2}'.format(self.relation_level_code, self.relation_level_cn, self.relation_level_en)


class Client(models.Model):
    name = models.CharField(_('姓名'), max_length=100)
    gender = models.CharField(_('性别'), max_length=10, choices=(('F', '女'), ('M', '男')), null=True, blank=True)
    mobile = models.CharField(_('手机'), max_length=100, null=True, blank=True)
    fax = models.CharField(_('传真'), max_length=100, null=True, blank=True)
    wechat = models.CharField(_('微信'), max_length=100, null=True, blank=True)
    email = models.EmailField(_('邮箱'), max_length=100, null=True, blank=True)
    company = models.CharField(_('公司名称'), max_length=100, null=True, blank=True)
    company_address = models.TextField(_('公司地址'), max_length=400, null=True, blank=True)
    post_address = models.TextField(_('邮寄地址'), max_length=400, null=True, blank=True)
    tax_code = models.CharField(_('税号'), max_length=100, null=True, blank=True)
    bank = models.CharField(_('银行'), max_length=200, null=True, blank=True)
    swift_code = models.CharField(_('Swift'), max_length=50, null=True, blank=True)
    bank_account = models.CharField(_('银行卡号'), max_length=50, null=True, blank=True)
    desc = models.TextField(_('介绍'), max_length=1000, null=True, blank=True)
    relation_level = models.ForeignKey(
        RelationLevel,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name=_('关系')
    )
    is_active = models.BooleanField(_('有联系'), default=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='client_created_by'
    )
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    def get_absolute_url(self):
        return reverse('{0}:client_detail'.format(app_name), kwargs={'pk': str(self.pk)})

    @property
    def related_orders(self):
        related_orders = Order.objects.filter(client__pk=self.pk).order_by('-datetime_created')
        if related_orders:
            return related_orders
        return None

    @property
    def order_count(self):
        related_orders = Order.objects.filter(client__pk=self.pk)
        if related_orders:
            return related_orders.count()
        return 0

    class Meta:
        ordering = ['-id']
        verbose_name = _('客户')
        verbose_name_plural = _('客户')

    def __str__(self):
        return '{0} {1}'.format(self.name, self.company)


class Salesman(models.Model):
    name = models.CharField(_('姓名'), max_length=100)
    gender = models.CharField(_('性别'), max_length=10, choices=(('F', '女'), ('M', '男')), null=True, blank=True)
    mobile = models.CharField(_('手机'), max_length=100, null=True, blank=True)
    wechat = models.CharField(_('微信'), max_length=100, null=True, blank=True)
    email = models.EmailField(_('邮箱'), max_length=100, null=True, blank=True)
    bank = models.CharField(_('银行'), max_length=200, null=True, blank=True)
    bank_account = models.CharField(_('银行卡号'), max_length=50, null=True, blank=True)
    desc = models.TextField(_('介绍'), max_length=1000, null=True, blank=True)
    is_active = models.BooleanField(_('在职'), default=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='salesman_created_by'
    )
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['id']
        verbose_name = _('销售员')
        verbose_name_plural = _('销售员')

    def __str__(self):
        return '{0} {1}'.format(self.name, self.mobile)


class TransportType(models.Model):
    transport_code = models.CharField(_('运输方式编号'), max_length=100, unique=True)
    transport_en = models.TextField(_('运输方式英文'), max_length=1000, unique=True)
    transport_cn = models.TextField(_('运输方式中文'), max_length=1000, unique=True)

    objects = models.Manager()

    class Meta:
        ordering = ['transport_code']
        verbose_name = _('运输方式')
        verbose_name_plural = _('运输方式')

    def __str__(self):
        return '[{0}] {1}'.format(self.transport_code, self.transport_cn)


class PayMethod(models.Model):
    pay_method_code = models.CharField(_('付款方式编号'), max_length=100, unique=True)
    pay_method_en = models.TextField(_('付款方式英文'), max_length=1000, unique=True)
    pay_method_cn = models.TextField(_('付款方式中文'), max_length=1000, unique=True)

    objects = models.Manager()

    class Meta:
        ordering = ['pay_method_code']
        verbose_name = _('付款方式')
        verbose_name_plural = _('付款方式')

    def __str__(self):
        return '[{0}] {1}'.format(self.pay_method_code, self.pay_method_cn)


class InstallationDesc(models.Model):
    installation_desc_code = models.CharField(_('安装说明编号'), max_length=100, unique=True)
    installation_desc_en = models.TextField(_('安装说明英文'), max_length=1000, unique=True)
    installation_desc_cn = models.TextField(_('安装说明中文'), max_length=1000, unique=True)

    objects = models.Manager()

    class Meta:
        ordering = ['installation_desc_code']
        verbose_name = _('安装说明')
        verbose_name_plural = _('安装说明')

    def __str__(self):
        return '[{0}] {1}'.format(self.installation_desc_code, self.installation_desc_cn)


class OrderNote(models.Model):
    order_note_code = models.CharField(_('附属条款编号'), max_length=100, unique=True)
    order_note_en = models.TextField(_('附属条款英文'), max_length=1000, unique=True)
    order_note_cn = models.TextField(_('附属条款中文'), max_length=1000, unique=True)

    objects = models.Manager()

    class Meta:
        ordering = ['order_note_code']
        verbose_name = _('附属条款')
        verbose_name_plural = _('附属条款')

    def __str__(self):
        return '[{0}] {1}'.format(self.order_note_code, self.order_note_cn)


class InstallationMaterial(models.Model):
    install_m_code = models.CharField(_('工程材料说明编号'), max_length=100, unique=True)
    install_m_en = models.TextField(_('工程材料说明英文'), max_length=1000, unique=True)
    install_m_cn = models.TextField(_('工程材料说明中文'), max_length=1000, unique=True)

    objects = models.Manager()

    class Meta:
        ordering = ['install_m_code']
        verbose_name = _('工程材料说明')
        verbose_name_plural = _('工程材料说明')

    def __str__(self):
        return '[{0}] {1}'.format(self.install_m_code, self.install_m_cn)


class ExportPrice(models.Model):
    export_price_unit = models.CharField(_('货币单位'), max_length=100, null=True)
    export_price_rate = models.DecimalField(_('利率'), max_digits=8, decimal_places=3)

    objects = models.Manager()

    class Meta:
        ordering = ['export_price_unit']
        verbose_name = _('出口价')
        verbose_name_plural = _('出口价')

    def __str__(self):
        return '[{0}] {1}'.format(self.export_price_unit, self.export_price_rate)


class OrderState(models.Model):
    order_state_code = models.CharField(_('订单状态编号'), max_length=100, unique=True)
    order_state_en = models.TextField(_('订单状态英文'), max_length=1000, unique=True)
    order_state_cn = models.TextField(_('订单状态中文'), max_length=1000, unique=True)
    can_view = models.BooleanField(_('别人可见'), default=False)
    can_edit = models.BooleanField(_('可以编辑'), default=True)
    is_confirmed = models.BooleanField(_('已经确认'), default=False)

    objects = models.Manager()

    class Meta:
        ordering = ['order_state_code']
        verbose_name = _('订单状态')
        verbose_name_plural = _('订单状态')

    def __str__(self):
        return '[{0}] {1}'.format(self.order_state_code, self.order_state_cn)


class Order(models.Model):
    order_code = models.CharField(_('订单编号'), max_length=100, unique=True)
    order_desc = models.CharField(_('订单描述'), max_length=100, null=True)
    transport_cost = models.DecimalField(_('运输费用'), max_digits=12, decimal_places=2, null=True, blank=True)
    install_cost = models.DecimalField(_('安装费用'), max_digits=12, decimal_places=2, null=True, blank=True)
    material_cost = models.DecimalField(_('材料费用'), max_digits=12, decimal_places=2, null=True, blank=True)
    deposit = models.DecimalField(_('订金'), max_digits=12, decimal_places=2, null=True, blank=True)
    total_price = models.DecimalField(_('总价'), max_digits=12, decimal_places=2, null=True, blank=True)
    total_discount = models.DecimalField(_('总折扣'), max_digits=12, decimal_places=2, null=True, blank=True)
    received = models.DecimalField(_('已收款'), max_digits=12, decimal_places=2, null=True, blank=True)
    need_to_pay = models.DecimalField(_('待支付'), max_digits=12, decimal_places=2, null=True, blank=True)
    price_all_final = models.DecimalField(_('最终总价'), max_digits=12, decimal_places=2, null=True, blank=True)  # Price
    order_create_date = models.DateField(_('创建日期'))
    order_validity_date_delta = models.IntegerField(_('有效期限/天'), default=15)
    order_deposit_pay_date = models.DateField(_('订金付款日期'), null=True, blank=True)
    order_final_pay_date = models.DateField(_('尾款支付日期'), null=True, blank=True)
    order_install_finish_date = models.DateField(_('安装完成日期'), null=True, blank=True)
    deposit_payed = models.BooleanField(_('订金是否支付'), default=False)
    final_payed = models.BooleanField(_('尾款是否支付'), default=False)
    bank_account = models.ForeignKey(
        BankAccount,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('收款账户')
    )
    order_pay_method = models.ForeignKey(
        PayMethod,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('付款方式'),
    )
    installation_desc = models.ForeignKey(
        InstallationDesc,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('安装调试说明'),
    )
    Installation_materials = models.ForeignKey(
        InstallationMaterial,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('工程材料说明'),
    )
    order_notes = models.ForeignKey(
        OrderNote,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('附属条款'),
    )
    manufacturing_days = models.IntegerField(_('制造日期/天'), default=50, null=True, blank=True)
    transport_type = models.ForeignKey(
        TransportType,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('运输方式'),
    )
    client = models.ForeignKey(
        Client,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name=_('客户'),
        limit_choices_to={'is_active': True}
    )
    salesman = models.ForeignKey(
        Salesman,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name=_('销售员'),
        limit_choices_to={'is_active': True}
    )
    sub_company = models.ForeignKey(
        SubCompany,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name=_('对接公司'),
    )
    export_price = models.ForeignKey(
        ExportPrice,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('出口价格'),
    )
    order_state = models.ForeignKey(
        OrderState,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('订单状态'),
    )
    success_rate = models.IntegerField(_('成交可能性'), default=50, null=True)
    tax_rate = models.IntegerField(_('税率'), null=True, default=13, blank=True)
    is_active = models.BooleanField(_('有效'), default=True)
    is_success = models.BooleanField(_('已经成交'), default=False)
    app_notes = models.TextField(_('订单备注'), max_length=5000, null=True, blank=True)
    show_app_notes = models.BooleanField(_('显示备注'), default=False)
    order_file = models.FileField(_('报价单'), upload_to='{0}/od'.format(app_name),
                                  null=True, blank=True)
    order_file_c = models.FileField(_('合同'), upload_to='{0}/od'.format(app_name),
                                    null=True, blank=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='order_created_by'
    )
    cooperators = models.ManyToManyField(
        User,
        blank=True,
        verbose_name=_('合作者'),
        related_name='order_cooperators'
    )
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    @property
    def total_power(self):
        _('总功率')
        t_p = 0
        try:
            equipments = ItemList.objects.filter(order_id=self.pk)
            if equipments:
                for eq in equipments:
                    if eq.equipment.power and eq.amount:
                        t_p += eq.equipment.power * eq.amount
            return t_p
        except ObjectDoesNotExist:
            return t_p

    def calculate_percentage(self):
        percentage = 0
        if self.manufacturing_days:
            if self.order_deposit_pay_date:
                delta_days = (timezone.localdate() - self.order_deposit_pay_date).days
                percentage = round(int(delta_days) / int(getattr(self, 'manufacturing_days')), 2)
        return percentage

    @property
    def order_validity_date(self):
        if self.order_create_date and self.order_validity_date_delta:
            return getattr(self, 'order_create_date') + timedelta(days=getattr(self, 'order_validity_date_delta'))
        return None

    @property
    def order_key(self):
        if self.datetime_created and self.order_code:
            access_key = hashlib.md5()
            access_key_c = '{0}{1}{2}'.format(GeneralConfig.order_key_generate, self.order_code,
                                              self.datetime_created).encode("utf8")
            access_key.update(access_key_c)
            return str(access_key.hexdigest())
        return None

    # @property
    # def total_price_auto(self):
    #     _('总价-auto')
    #     if self.export_price:
    #         if self.export_price.export_price_rate:
    #             return round(self.total_price / self.export_price.export_price_rate, 2)
    #         return self.total_price
    #     return None

    # @property
    # def total_discount_auto(self):
    #     _('总折扣-auto')
    #     if self.export_price:
    #         if self.export_price.export_price_rate:
    #             return round(self.total_discount / self.export_price.export_price_rate, 2)
    #     return self.total_discount

    @property
    def total_need_to_pay(self):  # 包含运费、安装费用和材料费用, 未包含税收
        _('折扣后总价')
        if self.total_price:
            if self.total_discount:
                return round(getattr(self, 'total_price') - getattr(self, 'total_discount'), 2)
            else:
                return self.total_price
        return None

    @property
    def transport_cost_auto(self):
        _('运输费用-auto')
        if self.transport_cost:
            if self.export_price:
                export_price_rate = getattr(self.export_price, 'export_price_rate', None)
                if export_price_rate:
                    return calculate_price(getattr(self, 'transport_cost') / export_price_rate)
        return self.transport_cost

    @property
    def install_cost_auto(self):
        _('安装费用-auto')
        if self.install_cost:
            if self.export_price:
                export_price_rate = getattr(self.export_price, 'export_price_rate', None)
                if export_price_rate:
                    return calculate_price(getattr(self, 'install_cost') / export_price_rate)
        return self.install_cost

    @property
    def material_cost_auto(self):
        _('安装材料费用-auto')
        if self.material_cost:
            if self.export_price:
                export_price_rate = getattr(self.export_price, 'export_price_rate', None)
                if export_price_rate:
                    return calculate_price(getattr(self, 'material_cost') / export_price_rate)
        return self.material_cost

    @property
    def price_unit(self):
        _('价格单位')
        if self.export_price:
            return getattr(self.export_price, 'export_price_unit', '元')
        return '元'

    @property
    def price_tax(self):
        if self.total_need_to_pay and self.tax_rate:
            if getattr(self, 'tax_rate') > 0:
                return self.total_need_to_pay * getattr(self, 'tax_rate') / 100
        return 0

    @property
    def price_with_tax(self):
        if self.need_to_pay:
            return self.need_to_pay
        if self.total_need_to_pay:
            if self.tax_rate:
                return self.total_need_to_pay * (100 + getattr(self, 'tax_rate')) / 100
            return self.total_need_to_pay
        return None

    @property
    def next_index(self):
        item_ls = ItemList.objects.filter(order_id=self.pk).order_by('-order_index')
        if item_ls.exists():
            next_index_code = item_ls.first().order_index
            if next_index_code:
                return next_index_code + 5
        return 1

    objects = models.Manager()

    class Meta:
        ordering = ['-datetime_created']
        verbose_name = _('订单')
        verbose_name_plural = _('订单')
        permissions = (
            ("view_contract", _("可以查看报价单和合同")),
            ("view_production_list", _("可以查看工程单")),
            ("change_production_list",  _("可以备注工程单")),
            ("view_all_orders", _("可以查看所有订单")),
        )

    def get_absolute_url(self):
        return reverse('{0}:order_detail'.format(app_name), kwargs={'pk': str(self.pk)})

    def __str__(self):
        return '{0} {1}'.format(self.order_code, self.client)


class ItemList(models.Model):
    order = models.ForeignKey(
        Order,
        on_delete=models.CASCADE,
        verbose_name=_('订单'),
        limit_choices_to={'is_active': True}
    )
    equipment = models.ForeignKey(
        Equipment,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name=_('设备'),
        limit_choices_to={'is_active': True}
    )
    initial_price_each = models.DecimalField(_('单价'), max_digits=12, decimal_places=2, null=True, blank=True)
    amount = models.IntegerField(_('数量'), default=1)
    order_index = models.IntegerField(_('排序参数'), default=10)
    equipment_notes = models.TextField(_('设备备注'), max_length=500, null=True, blank=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='item_list_created_by'
    )
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    def get_absolute_url(self):
        order_id = getattr(self.order, 'pk')
        if order_id:
            return reverse('{0}:order_detail'.format(app_name), args=[order_id])
        return reverse('{0}:order_list'.format(app_name))

    @property
    def item_basic_price_auto(self):  # 用户设定币种的价格，如果没有设定币种，则返回设备原价
        _('原价-auto')
        basic_price = getattr(self.equipment, 'basic_price', None)
        if basic_price:
            export_price = getattr(self.order, 'export_price', None)
            if export_price:
                export_price_rate = getattr(export_price, 'export_price_rate', None)
                if export_price_rate:
                    return calculate_price(basic_price / export_price_rate)
            return basic_price
        return None

    @property
    def item_price_each_auto(self):
        _('折后单价-auto')
        initial_price_each = getattr(self, 'initial_price_each', None)
        if not initial_price_each:
            initial_price_each = getattr(self.equipment, 'basic_price', None)
        export_price = getattr(self.order, 'export_price', None)
        if export_price:
            export_price_rate = getattr(export_price, 'export_price_rate', None)
            if export_price_rate:
                if initial_price_each:
                    return calculate_price(initial_price_each / export_price_rate)
        return initial_price_each

    @property
    def item_discount_each(self):
        _('单项折扣')
        basic_price = getattr(self.equipment, 'basic_price', None)
        if self.initial_price_each and basic_price:
            if basic_price - self.initial_price_each > 0:
                return round((basic_price - self.initial_price_each), 2)
        return None

    @property
    def item_discount_each_auto(self):
        _('单项折扣-auto')
        if self.item_basic_price_auto and self.item_price_each_auto:
            if self.item_basic_price_auto - self.item_price_each_auto > 0:
                return round((self.item_basic_price_auto - self.item_price_each_auto), 2)
        return 0

    @property
    def item_total_price(self):
        _('小计')
        basic_price = getattr(self.equipment, 'basic_price', None)
        if basic_price and self.amount:
            return round(basic_price * getattr(self, 'amount', 1), 2)
        return None

    @property
    def item_total_price_auto(self):
        _('小计-auto')
        if self.item_basic_price_auto and self.amount:
            return round(self.item_basic_price_auto * getattr(self, 'amount', 1), 2)
        return None

    @property
    def item_final_price(self):
        _('终价')
        if self.initial_price_each and self.amount:
            return round(getattr(self, 'initial_price_each') * getattr(self, 'amount', 1), 2)
        return None

    @property
    def item_final_price_auto(self):
        _('终价-auto')
        if self.item_price_each_auto and self.amount:
            return round(self.item_price_each_auto * getattr(self, 'amount', 1), 2)
        return None

    @property
    def item_total_discount(self):
        _('总折扣')
        basic_price = getattr(self.equipment, 'basic_price', None)
        if self.initial_price_each and self.amount and basic_price:
            if basic_price - self.initial_price_each > 0:
                return round((basic_price - self.initial_price_each) * getattr(self, 'amount', 1), 2)
        return 0

    @property
    def item_total_discount_auto(self):
        _('总折扣-auto')
        basic_price = getattr(self.equipment, 'basic_price', None)
        if self.initial_price_each and self.amount and basic_price:
            if basic_price - self.initial_price_each > 0:
                item_total_discount_cny = round((basic_price - self.initial_price_each) * getattr(self, 'amount', 1), 2)
            else:
                return 0
            export_price = getattr(self.order, 'export_price', None)
            if export_price:
                export_price_rate = getattr(export_price, 'export_price_rate', None)
                if export_price_rate:
                    return self.item_discount_each_auto * getattr(self, 'amount', 1)
            return item_total_discount_cny
        return 0

    class Meta:
        ordering = ['id']
        verbose_name = _('订单明细')
        verbose_name_plural = _('订单明细')

    def __str__(self):
        return '{0} {1}'.format(self.order, self.equipment)


class TransferRecord(models.Model):
    order = models.ForeignKey(
        Order,
        on_delete=models.CASCADE,
        verbose_name=_('订单'),
        limit_choices_to={'is_active': True}
    )
    confirmed = models.BooleanField(_('是否成交'), default=False)
    transfer_amount = models.DecimalField(_('转账金额'), max_digits=12, decimal_places=2, null=True, blank=True)
    transfer_datetime = models.DateTimeField(_('转账时间'))
    transfer_account_to = models.ForeignKey(
        BankAccount,
        on_delete=models.SET_NULL,
        null=True,
        limit_choices_to={'is_active': True},
        verbose_name=_('收款账户')
    )
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='transfer_record_created_by'
    )
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-id']
        verbose_name = _('转账记录')
        verbose_name_plural = _('转账记录')

    def __str__(self):
        return '{0} [{1}]元 {2}'.format(self.order, self.transfer_amount, self.transfer_datetime)


class ServiceState(models.Model):
    service_state_code = models.CharField(_('服务状态编号'), max_length=100, unique=True)
    service_state_en = models.CharField(_('服务状态英文'), max_length=100, unique=True)
    service_state_cn = models.CharField(_('服务状态中文'), max_length=100, unique=True)

    objects = models.Manager()

    class Meta:
        ordering = ['service_state_code']
        verbose_name = _('服务状态')
        verbose_name_plural = _('服务状态')

    def __str__(self):
        return '[{0}] {1}'.format(self.service_state_code, self.service_state_cn)


class ServiceRecord(models.Model):
    title = models.CharField(_('标题'), max_length=100, null=True)
    related_order = models.ForeignKey(
        Order,
        on_delete=models.CASCADE,
        verbose_name=_('订单'),
        null=True,
    )
    salesman = models.ForeignKey(
        Salesman,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name=_('销售员'),
    )
    service_state = models.ForeignKey(
        ServiceState,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name=_('服务状态'),
    )
    service_date = models.DateField(_('日期'), null=True)
    remarks = models.TextField(_('备注'), max_length=4000, null=True, blank=True)
    is_hide = models.BooleanField(_('隐藏'), default=False)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='service_record_created_by'
    )
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-id']
        verbose_name = _('服务记录')
        verbose_name_plural = _('服务记录')

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:service_record_list'.format(app_name))

    def __str__(self):
        return '{0} {1} {2}'.format(self.related_order, getattr(self.related_order, 'client'), self.datetime_created)


class AnnounceTag(models.Model):
    announce_tag = models.CharField(_('公告标签'), max_length=100, null=True)
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['announce_tag']
        verbose_name = _('公告标签')
        verbose_name_plural = _('公告标签')

    def __str__(self):
        return '[{0}] {1}'.format(self.pk, self.announce_tag)


class Announce(models.Model):
    title = models.CharField(_('标题'), max_length=100, null=True)
    remarks = models.TextField(_('内容'), max_length=4000, null=True, blank=True)
    announce_tag = models.ManyToManyField(
        AnnounceTag,
        blank=True,
        verbose_name=_('公告标签')
    )
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='announce_created_by'
    )
    is_show = models.BooleanField(_('显示'), default=True)
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    @property
    def announced_by(self):
        if self.created_by:
            try:
                ab = self.created_by
                if ab:
                    return '{0}{1}'.format(getattr(ab, 'last_name'), getattr(ab, 'first_name'))
            except ObjectDoesNotExist:
                pass
        return _('办公室')

    class Meta:
        ordering = ['-datetime_created']
        verbose_name = _('公告')
        verbose_name_plural = _('公告')

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:home'.format(app_name))

    def __str__(self):
        return '[{0}] {1}'.format(self.pk, self.title)


class EquipmentList(models.Model):
    title = models.CharField(_('标题'), max_length=100, null=True)
    equipment_list = ArrayField(ArrayField(models.IntegerField(), size=3))
    is_show = models.BooleanField(_('显示'), default=True)
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-datetime_created']
        verbose_name = _('设备列表')
        verbose_name_plural = _('设备列表')

    @property
    def get_equipment_list(self):
        equipment_list = getattr(self, 'equipment_list')
        if equipment_list:
            new_el = list()
            for e in equipment_list:
                new_e = dict()
                if len(e) == 3:
                    new_e['index'] = e[0]
                    new_e['equipment'] = Equipment.objects.get(pk=e[1]).equipment_cn
                    new_e['amount'] = e[2]
                new_el.append(new_e)
            return new_el

    @property
    def get_options(self):
        equipment_list = getattr(self, 'equipment_list')
        if equipment_list:
            new_el = list()
            for e in equipment_list:
                new_e = ''
                if len(e) == 3:
                    new_e += '[{0}] {1}:{2}'.format(e[0], Equipment.objects.get(pk=e[1]).equipment_cn, e[2])
                new_el.append(new_e)
            return new_el

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:batch_equipment_list'.format(app_name))

    def __str__(self):
        return '[{0}] {1}'.format(self.pk, self.equipment_list)


class Warehouse(models.Model):
    name = models.CharField(_('仓库名称'), max_length=100, null=True)
    desc = models.TextField(_('描述'), max_length=1000, null=True, blank=True)
    show = models.BooleanField(_('显示'), default=True)
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['pk']
        verbose_name = _('仓库')
        verbose_name_plural = _('仓库')

    # def get_absolute_url(self):
    #     if self.pk:
    #         pass
    #     return reverse('{0}:warehouse_list'.format(app_name))

    def __str__(self):
        return '[{0}] {1}'.format(self.pk, self.name)


class EquipmentIn(models.Model):
    warehouse = models.ForeignKey(
        Warehouse,
        on_delete=models.CASCADE,
        verbose_name=_('仓库'),
        null=True,
    )
    equipment = models.ForeignKey(
        Equipment,
        on_delete=models.CASCADE,
        verbose_name=_('设备'),
        null=True,
    )
    amount = models.IntegerField(_('数量'), default=1)
    cost = models.DecimalField(_('成本-单价'), max_digits=12, decimal_places=2, null=True, blank=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='equipment_in_created_by'
    )
    can_sale = models.BooleanField(_('可销售'), default=True)
    notes = models.TextField(_('备注'), max_length=1000, null=True, blank=True)
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-pk']
        verbose_name = _('设备入库')
        verbose_name_plural = _('设备入库')

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:equipment_in_list'.format(app_name))

    def __str__(self):
        return '[{0}] {1} {2} {3}'.format(self.pk, self.warehouse, self.equipment, self.amount)


class EquipmentOut(models.Model):
    warehouse = models.ForeignKey(
        Warehouse,
        on_delete=models.CASCADE,
        verbose_name=_('仓库'),
        null=True,
    )
    equipment = models.ForeignKey(
        Equipment,
        on_delete=models.CASCADE,
        verbose_name=_('设备'),
        null=True,
    )
    amount = models.IntegerField(_('数量'), default=1)
    price = models.DecimalField(_('出售金额'), max_digits=12, decimal_places=2, null=True, blank=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='equipment_out_created_by'
    )
    is_confirmed = models.BooleanField(_('已确认'), default=True)
    notes = models.TextField(_('备注'), max_length=1000, null=True, blank=True)
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-pk']
        verbose_name = _('设备出库')
        verbose_name_plural = _('设备出库')

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:equipment_out_list'.format(app_name))

    def __str__(self):
        return '[{0}] {1} {2} {3}'.format(self.pk, self.warehouse, self.equipment, self.amount)


class EquipmentAssembly(models.Model):
    assembly_name = models.CharField(_('组装名称'), max_length=100, unique=True)
    equipment = models.ForeignKey(
        Equipment,
        on_delete=models.CASCADE,
        verbose_name=_('设备'),
        null=True,
    )
    is_confirmed = models.BooleanField(_('已确认'), default=True)
    is_active = models.BooleanField(_('可用'), default=True)
    notes = models.TextField(_('备注'), max_length=1000, null=True, blank=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='equipment_assembly_created_by'
    )
    cooperators = models.ManyToManyField(
        User,
        blank=True,
        verbose_name=_('合作者'),
        related_name='assembly_cooperators'
    )
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-pk']
        verbose_name = _('设备组装')
        verbose_name_plural = _('设备组装')

    @property
    def assembly_list(self):
        assembly_list = AssemblyItem.objects.filter(equipment_assembly_id=self.pk).order_by('order_index')
        if assembly_list.exists():
            return assembly_list
        else:
            return None

    @property
    def total_value(self):
        total_value = 0
        assembly_list = AssemblyItem.objects.filter(equipment_assembly_id=self.pk)
        if assembly_list.exists():
            for a_i in assembly_list:
                if a_i.total_value:
                    total_value += a_i.total_value
        return total_value

    @property
    def next_index(self):
        assembly_list = AssemblyItem.objects.filter(equipment_assembly_id=self.pk).order_by('-order_index')
        if assembly_list.exists():
            next_index_code = assembly_list.first().order_index
            if next_index_code:
                return next_index_code + 5
        return 1

    def get_absolute_url(self):
        if self.pk:
            return reverse('{0}:equipment_assembly_detail'.format(app_name), args=[self.pk])
        else:
            return reverse('{0}:equipment_assembly_list'.format(app_name))

    def __str__(self):
        return '[{0}] {1}'.format(self.pk, self.assembly_name)


class AssemblyItem(models.Model):
    equipment_assembly = models.ForeignKey(
        EquipmentAssembly,
        on_delete=models.CASCADE,
        verbose_name=_('组装名称'),
        null=True,
    )
    equipment = models.ForeignKey(
        Equipment,
        on_delete=models.CASCADE,
        verbose_name=_('子设备'),
        null=True,
    )
    order_index = models.IntegerField(_('排序参数'), default=10)
    amount = models.IntegerField(_('数量'), default=1)
    notes = models.TextField(_('备注'), max_length=1000, null=True, blank=True)
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['order_index']
        verbose_name = _('组装部件')
        verbose_name_plural = _('组装部件')

    @property
    def total_value(self):
        if self.equipment:
            basic_price = getattr(self.equipment, 'basic_price', None)
            if basic_price:
                total_value = basic_price * self.amount
                return total_value
        return None

    @property
    def amount_left(self):
        if self.equipment:
            return getattr(self.equipment, 'amount_left', 0)
        return 0

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:equipment_assembly_list'.format(app_name))

    def __str__(self):
        return '{0} * {1}'.format(self.equipment, self.amount)


class PlanAssembly(models.Model):
    related_equipment_assembly = models.OneToOneField(
        EquipmentAssembly,
        null=True,
        on_delete=models.CASCADE,
        verbose_name=_('组装名称'),
    )
    amount = models.IntegerField(_('数量'), default=1)
    related_orders = models.ManyToManyField(
        Order,
        blank=True,
        verbose_name=_('相关订单'),
    )
    notes = models.TextField(_('备注'), max_length=1000, null=True, blank=True)
    is_ordered = models.BooleanField(_('已经采购'), default=False)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='plan_assembly_created_by'
    )
    datetime_created = models.DateTimeField(_('添加时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-datetime_updated']
        verbose_name = _('部件采购')
        verbose_name_plural = _('部件采购')

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:plan_assembly_detail'.format(app_name), kwargs={'pk': str(self.pk)})

    def __str__(self):
        return '{0} * {1}'.format(self.related_equipment_assembly, self.amount)


class FixedAssetsType(models.Model):
    fixed_assets_type = models.CharField(_('固定资产类型'), max_length=200, null=True)
    notes = models.TextField(_('描述'), max_length=1000, null=True, blank=True)
    datetime_created = models.DateTimeField(_('记录时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('最后更新'), auto_now=True)

    objects = models.Manager()

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:add_fixed_assets_type'.format(app_name))

    class Meta:
        ordering = ['id']
        verbose_name = _('固定资产类型')
        verbose_name_plural = _('固定资产类型')

    def __str__(self):
        return '{0}'.format(self.fixed_assets_type)


class FixedAssets(models.Model):
    name_of_asset = models.CharField(_('名称'), max_length=200, null=True)
    specifications = models.CharField(_('规格'), max_length=200, null=True)
    fixed_assets_type = models.ForeignKey(
        FixedAssetsType,
        on_delete=models.SET_NULL,
        null=True,
        verbose_name=_('固定资产类型'),
    )
    notes = models.TextField(_('描述'), max_length=2000, null=True, blank=True)
    datetime_created = models.DateTimeField(_('记录时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('最后更新'), auto_now=True)

    objects = models.Manager()

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:fixed_assets_list'.format(app_name))

    @property
    def total_in(self):
        ti = FixedAssetsIn.objects.filter(fixed_assets_id=self.pk).aggregate(amount=Sum('amount'))
        if ti:
            if ti['amount']:
                return ti['amount']
        return 0

    @property
    def total_out(self):
        ti = FixedAssetsOut.objects.filter(fixed_assets_id=self.pk).aggregate(amount=Sum('amount'))
        if ti:
            if ti['amount']:
                return ti['amount']
        return 0

    @property
    def total_left(self):
        return round(float(self.total_in) - float(self.total_out))

    @property
    def total_value(self):
        avg_price = FixedAssetsIn.objects.filter(
            fixed_assets_id=self.pk).filter(price_each__gte=0).aggregate(price_each=Avg('price_each'))
        if avg_price:
            if avg_price['price_each']:
                return round(avg_price['price_each']*self.total_left, 2)
        return 0

    class Meta:
        ordering = ['-id']
        verbose_name = _('固定资产')
        verbose_name_plural = _('固定资产')

    def __str__(self):
        return '{0} ({1}) 剩余:[{2}]'.format(self.name_of_asset, self.specifications, self.total_left)


class FixedAssetsIn(models.Model):
    fixed_assets = models.ForeignKey(
        FixedAssets,
        on_delete=models.CASCADE,
        null=True,
        verbose_name=_('固定资产'),
    )
    price_each = models.DecimalField(_('单价'), max_digits=8, decimal_places=2, null=True)
    amount = models.IntegerField(_('数量'), null=True, blank=True)
    date_of_purchase = models.DateField(_('购买日期'), null=True, blank=True)
    warranty_period = models.DateField(_('质保期限'), null=True, blank=True)
    is_confirmed = models.BooleanField(_('是否确认'), default=True)
    notes = models.TextField(_('备注'), max_length=1000, null=True, blank=True)
    datetime_created = models.DateTimeField(_('记录时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('最后更新'), auto_now=True)

    objects = models.Manager()

    @property
    def total_value(self):
        if self.price_each and self.amount:
            return round(float(getattr(self, 'amount')) * float(getattr(self, 'price_each')), 2)
        return 0

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:fixed_assets_list'.format(app_name))

    class Meta:
        ordering = ['-id']
        verbose_name = _('固定资产入库')
        verbose_name_plural = _('固定资产入库')

    def __str__(self):
        return '{0} {1} {2}'.format(self.fixed_assets, self.price_each, self.amount)


class FixedAssetsOut(models.Model):
    fixed_assets = models.ForeignKey(
        FixedAssets,
        on_delete=models.CASCADE,
        null=True,
        verbose_name=_('固定资产'),
    )
    amount = models.IntegerField(_('数量'), null=True, blank=True)
    date_of_out = models.DateField(_('出库日期'), null=True, blank=True)
    is_confirmed = models.BooleanField(_('是否确认'), default=True)
    notes = models.TextField(_('备注'), max_length=1000, null=True, blank=True)
    datetime_created = models.DateTimeField(_('记录时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('最后更新'), auto_now=True)

    objects = models.Manager()

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:fixed_assets_list'.format(app_name))

    class Meta:
        ordering = ['-id']
        verbose_name = _('固定资产出库')
        verbose_name_plural = _('固定资产出库')

    def __str__(self):
        return '{0} {1} {2}'.format(self.fixed_assets, self.amount, self.date_of_out)


class InOutType(models.Model):
    in_out_type = models.CharField(_('收支类型'), max_length=200)
    is_out = models.BooleanField(_('是支出'), default=False)
    datetime_created = models.DateTimeField(_('记录时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['id']
        verbose_name = _('收支类型')
        verbose_name_plural = _('收支类型')

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:in_out_type_list'.format(app_name))

    def __str__(self):
        return '{0}'.format(self.in_out_type)


class InOut(models.Model):
    in_out_date = models.DateField(_('收支日期'), null=True)
    in_out_type = models.ForeignKey(
        InOutType,
        null=True,
        on_delete=models.SET_NULL,
        verbose_name=_('收支类型')
    )
    amount = models.DecimalField(_('金额'),  max_digits=8, decimal_places=2, null=True)
    left_before = models.DecimalField(_('结余'), max_digits=8, decimal_places=2, null=True, blank=True)
    desc = models.CharField(_('描述'), max_length=200, null=True, blank=True)
    linked_order = models.ForeignKey(
        Order,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        verbose_name=_('关联订单'),
    )
    invoice = models.FileField(_('账单'), upload_to='main/inout', null=True, blank=True)
    is_confirmed = models.BooleanField(_('是否确认'), default=True)
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('创建者'),
        related_name='inout_created_by'
    )
    datetime_created = models.DateTimeField(_('记录时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(_('最后更新'), auto_now=True)

    def get_absolute_url(self):
        if self.pk:
            pass
        return reverse('{0}:in_out_list'.format(app_name))

    objects = models.Manager()

    class Meta:
        ordering = ['-id']
        verbose_name = _('收支明细')
        verbose_name_plural = _('收支明细')

    def __str__(self):
        return '{0} {1} {2} {3}'.format(self.in_out_date, self.amount, self.in_out_type, self.desc)

    def save(self, *args, **kwargs):
        amount = self.amount
        if amount:
            if self.in_out_type:
                is_out = getattr(self.in_out_type, 'is_out', False)
                if is_out and amount > 0:
                    self.amount = - amount
                if not self.left_before:
                    if self.pk:
                        m_s = InOut.objects.filter(pk__lt=self.pk).aggregate(money_left_b=Sum('amount'))
                    else:
                        m_s = InOut.objects.aggregate(money_left_b=Sum('amount'))
                    if m_s:
                        if m_s['money_left_b']:
                            self.left_before = m_s['money_left_b'] + self.amount
                        else:
                            self.left_before = self.amount
        super(InOut, self).save(*args, **kwargs)
